package com.spider.im.chat.message.group;


import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.protobuf.Parser;
import com.spider.im.chat.entity.ChatGroupUser;
import com.spider.im.chat.message.AbstractMessageStrategy;
import com.spider.im.chat.annotation.MessageTypeHandler;
import com.spider.im.chat.proto.ChatProto;
import com.spider.im.chat.req.ChatGroupUserReq;
import com.spider.im.chat.service.ChatGroupService;
import com.spider.im.chat.service.ChatGroupUserService;
import com.spider.im.common.aspect.BusinessException;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.internal.ThrowableUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@Slf4j
@MessageTypeHandler(type = ChatProto.MessageType.INVITE_GROUP)
public class GroupUserStrategy extends AbstractMessageStrategy<ChatProto.InviteGroupRequest> {

    @Resource
    public RedissonClient redissonClient;

    @Resource
    public ChatGroupService chatGroupService;

    @Resource
    public ChatGroupUserService chatGroupUserService;


    @Override
    public Parser<ChatProto.InviteGroupRequest> getParser() {
        return ChatProto.InviteGroupRequest.parser();
    }

    /**
     * 处理登录请求
     * @param ctx
     * @param message
     */
    @Override
    public void handle(ChannelHandlerContext ctx, ChatProto.InviteGroupRequest message) {

        log.info("邀请成员群聊: {}", message);
        ChatGroupUserReq chatGroupUserReq = new ChatGroupUserReq();
        Long groupId = message.getGroupId();
        chatGroupUserReq.setGroupId(groupId);
        chatGroupUserReq.setUserIds(message.getGroupUsersList());
        try {
            List<Long> groupUserIds = chatGroupUserService.saveGroupUser(chatGroupUserReq);
            //查询群组成员，给在线的成员发送消息
            //获取群聊的在线用户
            List<ChatGroupUser> chatGroupUserList = chatGroupUserService.list(new LambdaQueryWrapper<ChatGroupUser>().eq(ChatGroupUser::getGroupId, groupId));
            if (CollectionUtil.isEmpty(chatGroupUserList)) {
                log.warn("组TargetGroupId {} 没有人. Message not sent.", groupId);
                return;
            }
            String groupMassage = "用户 " + message.getUserId() + "邀请 " + CollectionUtil.join(groupUserIds,",") + "加入群 " + groupId;
            //拼装消息
            ChatProto.MessageWrapper wrapper = getMessageWrapper(true, groupMassage);
            //遍历群聊的在线用户,发送消息
            chatGroupUserList.forEach(chatGroupUser -> {
                Channel targetChannel = activeChannels.get(chatGroupUser.getUserId());
                if (targetChannel != null && targetChannel.isActive()) {
                    log.info("给用户发送消息 {},message:{}.", chatGroupUser.getUserId(),groupMassage);
                    targetChannel.writeAndFlush(wrapper);
                    this.sendResponse(targetChannel, wrapper);
                } else {
                    log.warn("用户 {} 不在线. Message not sent.", chatGroupUser.getUserId());
                }
            });
            sendResponse(ctx.channel(), getMessageWrapper(true, groupId.toString()));
        } catch (BusinessException e) {
            log.warn("邀请成员进群失败: {}", e.getMessage());
            sendResponse(ctx.channel(), getMessageWrapper(true, e.getMessage()));
        } catch (Exception e) {
            log.error("邀请成员进群失败: {}", ThrowableUtil.stackTraceToString(e));
            sendResponse(ctx.channel(), getMessageWrapper(false, "邀请成员进群失败"));
        }
    }

    /**
     * 构建消息包装
     *
     * @return
     */
    private static ChatProto.MessageWrapper getMessageWrapper(boolean success, String message) {
        ChatProto.Response response = ChatProto.Response.newBuilder()
                .setSuccess(success)
                .setMessage(message)
                .build();
        return ChatProto.MessageWrapper.newBuilder()
                .setType(ChatProto.MessageType.INVITE_GROUP)
                .setPayload(response.toByteString())
                .build();
    }
}
